home *** CD-ROM | disk | FTP | other *** search
- /* $Id: sort.c,v 1.1 1993/09/17 06:24:05 ppessi Exp $
- *
- * sort.c -- sort a table using quicksort
- *
- * Author: ppessi <Pekka.Pessi@hut.fi>
- *
- * Copyright (c) 1992 Pekka Pessi
- * All rights reserved
- *
- * Created : Thu Dec 3 11:21:42 1992 ppessi
- * Last modified: Thu Dec 3 11:57:51 1992 ppessi
- *
- */
-
- #ifdef NOMYDEBUG
- #define MYDEBUG( x )
- #else
- #include <clib/dos_protos.h>
- #define MYDEBUG(x) x
- #endif
-
- static void
- _quick_sort(void *slots[], int left, int right, int(*compare)(void *, void *))
- {
- void *ld, *rd, *md, *sd;
- int middle, l, r;
-
- remove_tail:
- if (right - left < 8) /* we left this for insertion sort */
- return;
- /* Find median */
- middle = (left + right) / 2;
- ld = slots[left];
- md = slots[middle];
- rd = slots[right];
-
- MYDEBUG( FPrintf(Stderr,
- "Left (%ld): %s, middle (%ld): %s, right (%ld): %s\n",
- left, ld -> ed_Name,
- middle, md -> ed_Name,
- right, rd -> ed_Name) );
-
- if ((compare)(ld, rd) > 0)
- sd = rd, rd = ld, ld = sd; /* swap */
-
- if ((compare)(ld, md) > 0)
- sd = md, md = ld, ld = sd; /* swap */
-
- if ((compare)(md, rd) > 0)
- sd = md, md = rd, rd = sd; /* swap */
-
- slots[right] = rd;
- slots[middle] = slots[right - 1];
- slots[left] = ld;
- /* use median as a sentinel and partitioning element */
- slots[right - 1] = md;
-
- MYDEBUG( FPrintf(Stderr, "Left: %s, middle: %s, right: %s\n",
- ld -> ed_Name, md -> ed_Name, rd -> ed_Name) );
-
- for (l = left, r = right - 1; l < r; ) {
- /* scan from left */
- do {l++;} while ((compare)(md, slots[l]) >= 0);
-
- MYDEBUG( FPrintf(Stderr, "Left %s \n", slots[l] -> ed_Name) );
- /* scan from right */
- do {r--;} while ((compare)(slots[r], md) >= 0);
-
- MYDEBUG( FPrintf(Stderr, "Right %s \n", slots[r] -> ed_Name) );
-
- if (l < r)
- ld = slots[l], slots[l] = slots[r], slots[r] = ld; /* swap elements */
- }
- /* move partition element into partition place */
- md = slots[right - 1], slots[right - 1] = slots[l], slots[l] = md;
-
- if (l > middle) { /* sort smaller partition recursively */
- _quick_sort(slots, l + 1, right, compare);
- right = l - 1;
- } else {
- _quick_sort(slots, left, l - 1, compare);
- left = l + 1;
- }
- goto remove_tail; /* remove tail recursion */
- }
-
- /*
- Actual quick_sort does final sorting with insertion sort
- */
- void
- quick_sort(void *slots[], int size, int(*compare)(void *, void *))
- {
- register int i, j;
- MYDEBUG( register int distance; )
- register void *data;
-
- _quick_sort(slots, 0, size- 1, compare);
-
- for (j = 1; j < size; j++) {
- data = slots[j];
- i = j;
-
- MYDEBUG( distance = 0; )
-
- while (i > 0 && (compare)(data, slots[i-1]) < 0) {
- slots[i] = slots[i-1];
- i--;
-
- MYDEBUG( distance++; )
- }
- slots[i] = data;
- MYDEBUG( if (distance)
- FPrintf(Stderr, "Moved %s by %ld\n", data -> ed_Name, distance); )
- }
- }
-
-